//shape.cpp
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <iomanip>

#ifndef __SHAPE_H
#include "Shape.h"
#endif

using std::cout;
using std::cin;
using std::endl;
using std::setw;
using std::fixed;
using std::showpoint;
using std::left;

void drawLine(Line *l) {
    printf("Line p1(%d,%d) p2(%d,%d)\n", l->p1.x, l->p1.y, l->p2.x, l->p2.y);
}

void drawCircle(Circle *c) {
    printf("Circle center(%d,%d) radius=%d\n", c->center.x, c->center.y, c->radius);
}

void drawRect(Rect *r) {
    printf("Rect width p1(%d,%d) p2(%d,%d), heigth p1(%d,%d) p2(%d,%d)\n", r->width.p1.x, r->width.p1.y, r->width.p2.x, r->width.p2.y, r->heigth.p1.x, r->heigth.p1.y, r->heigth.p2.x, r->heigth.p2.y);
}

void translateLine(Line *l, Point p) {
    l->p1.x += p.x;
    l->p1.y += p.y;
    l->p2.x += p.x;
    l->p2.y += p.y;

    printf("Line p1(%d,%d) p2(%d,%d)\n", l->p1.x, l->p1.y, l->p2.x, l->p2.y);
}

void translateCircle(Circle *c, Point p) {
    c->center.x += p.x;
    c->center.y += p.y;

    printf("Circle center(%d,%d) radius=%d\n", c->center.x, c->center.y, c->radius);
}

void translateRect(Rect *r, Point p) {
    r->width.p1.x += p.x;
    r->width.p1.y += p.y;
    r->width.p2.x += p.x;
    r->width.p2.y += p.y;
    r->heigth.p1.x += p.x;
    r->heigth.p1.y += p.y;
    r->heigth.p2.x += p.x;
    r->heigth.p2.y += p.y;

    printf("Rect width p1(%d,%d) p2(%d,%d), heigth p1(%d,%d) p2(%d,%d)\n", r->width.p1.x, r->width.p1.y, r->width.p2.x, r->width.p2.y, r->heigth.p1.x, r->heigth.p1.y, r->heigth.p2.x, r->heigth.p2.y);
}

Line *createLine(Point p1, Point p2) {
    Line *l = (Line*) malloc(sizeof (Line));
    l->base.draw = (DrawFunc)drawLine;
    l->base.translate = (TranslateFunc)translateLine;
    l->base.next = 0;
    l->p1 = p1;
    l->p2 = p2;
    return l;
}

Circle *createCircle(Point center, int radius) {
    Circle *c = (Circle*) malloc(sizeof (Circle));
    c->base.draw = (DrawFunc)drawCircle;
    c->base.translate = (TranslateFunc)translateCircle;
    c->base.next = 0;
    c->center = center;
    c->radius = radius;
    return c;
}

Rect *createRect(Line width, Line heigth) {
    Rect *r = (Rect*) malloc(sizeof (Rect));
    r->base.draw = (DrawFunc)drawRect;
    r->base.translate = (TranslateFunc)translateRect;
    r->base.next = 0;
    r->width = width;
    r->heigth = heigth;
    return r;
}

Figure *createFigure() {
    Figure *f = (Figure*) malloc(sizeof (Figure));
    f->head = f->tail = 0;
    f->nbShapes = 0;
    return f;
}

void destroyFigure(Figure *f) {
    ShapeBase *lixo;
    while (f->head != NULL) {
        if (f->head == f->tail)
            f->tail = NULL;

        lixo = f->head;
        f->head = (f->head)->next;
        free(lixo);
        lixo = NULL;
    }
    free(f);
    f = NULL;
}

void addShape(Figure *f, ShapeBase *s) {
    if (f->head == 0)
        f->head = s;
    else
        f->tail->next = s;
    f->tail = s;
    f->nbShapes++;
}

void drawFigure(Figure *f) {
    for (ShapeBase *s = f->head; s != 0; s = s->next) {
        s->draw(s);
    }
}

void showMenu() {
    cout << fixed << showpoint;
    cout << left;
    cout << endl << endl << endl << setw(3) << " " << "Menu Figura" << endl << endl;
    cout << setw(3) << "L" << "criar linha" << endl;
    cout << setw(3) << "C" << "criar circulo" << endl;
    cout << setw(3) << "R" << "criar retangulo" << endl;
    cout << setw(3) << "D" << "desenhar figura" << endl;
    cout << setw(3) << "M" << "mover figura" << endl;
    cout << setw(3) << "X" << "sair" << endl << endl;
    cout << "Entre com uma alternativa: - ";
}//End showMenu

char getCommand() {
    char prompt = '0';
    cin >> prompt;
    return prompt;
}//End getCommand

Point getPoint(const char* p) {
    Point point;
    cout << "Ponto " << p << ": informe x: ";
    cin >> point.x;
    cout << "informe y: ";
    cin >> point.y;
    return point;
}//End getPoint

int getInt(const char* radius) {
    int raio;
    cout << radius << ": informe o valor do raio: ";
    cin >> raio;
    return raio;
}//End getInt

void translateFigure(Figure* f, Point p) {
    for (ShapeBase *s = f->head; s != 0; s = s->next) {
        s->translate(s, p);
    }
}
